package mybatis.mapper;

import mybatis.Utill.batisUtill;
import mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

public class cacheAndResultMap {

    @Test
    public void testSessionCache() throws IOException {
        /*
        mybatis的查询策略:
        当用户发起请求时，程序并不直接查询数据库而是先到一级缓存中检索没检索到就去二级缓存中找，如果检索到符合的缓存数据则直接返回结果，若缓存中没有则去数据库查询，查询结果会被先保存一份在缓存中然后再返回给程序递交给用户
        当执行增删改等对数据库产生更改的操作时，无论成功与否都会对一级缓存产生刷新效果，但如果没成功则不会对二级缓存产生刷新效果
        对于增删改查操作是否影响缓存是可以通过在标签中写flushCache设置来改变的 例如<select id="selectUser" resultType="com.example.User" flushCache="true">
         */
        //mybatis提供了对于查询的缓存功能以提高对于重复查询处理的效率 缓存分为一级缓存和二级缓存
        //一级缓存的作用域是session，即一次与数据库之间的会话，是默认开启的，如果想要使用一级缓存中的某个缓存信息需要注意保证所使用的session一直是同一个session
        String configResource = "mybatisConfugration.xml";
        InputStream stream = Resources.getResourceAsStream(configResource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream);
        //推送测试
        //SqlSessionFactory每开启一个数据库会话(openSession)时都会创建新的sqlsession对象，sqlsession对象包含一个executor 即执行器对象，该对象中有一个PerpetualCache对象，在一级缓存层级中不同的sqlsession不共享数据
        SqlSession session1 = factory.openSession();
        session1.selectOne("mybatis.mybatisMapper.cacheAndResultMap.sqlSessionCacheSelect",10);
//        调用.clearCache()方法会清空一级缓存，但该对象仍然可用，可以继续对后续的查询结果做缓存工作，执行增删改操作和这个会有一样的效果
        session1.clearCache();
//        如果没调用.clearCache()方法或者该session所属的namespace开启了cache缓存功能，则在控制台输出的日志中会显示 Cache Hit Ratio [mybatis.mybatisMapper.cacheAndResultMap]: 0.0；表示成功在缓存中命中了之前已经查询过的结果
        session1.selectOne("mybatis.mybatisMapper.cacheAndResultMap.sqlSessionCacheSelect", 10);
        SqlSession session2 = factory.openSession();
        session2.selectOne("mybatis.mybatisMapper.cacheAndResultMap.sqlSessionCacheSelect",10);
        //当会话被结束时，SqlSession以及内部的Executor,PerpetualCache对象都会被一并释放，一级缓存将不可用
//        session.close();

        //二级缓存的作用于是一个mapper的namespace(即一个映射文件的范围内共享数据)，是跨session共享的应用级缓存 详情请移步至mybatis/mybatisMapper/cacheAndResultMap.xml
    }

    @Test
    public void testCacheAndResultMap(){
        mybatis.mybatisMapper.cacheAndResultMap map = batisUtill.getSession().getMapper(mybatis.mybatisMapper.cacheAndResultMap.class);
        System.out.println(map.selectDeptByDno(10));
    }
}
